package com.tencent.sr.iris.activity.restapi;

import cn.hutool.core.util.StrUtil;
import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.Tracer;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.dangdang.ddframe.job.api.ShardingContext;
import com.dangdang.ddframe.job.executor.ShardingContexts;
import com.google.common.collect.ImmutableMap;
import com.tencent.sr.iris.activity.dependency.user.UserCoreDependency;
import com.tencent.sr.iris.activity.interfaces.dto.SceneInfoMappingDTO;
import com.tencent.sr.iris.activity.interfaces.event.dto.ActivityEventDTO;
import com.tencent.sr.iris.activity.interfaces.request.acticity.ActivityGiftPopupRequest;
import com.tencent.sr.iris.activity.interfaces.request.task.QuerySelfBuyGMVReq;
import com.tencent.sr.iris.activity.interfaces.request.task.UserBaseRequest;
import com.tencent.sr.iris.activity.interfaces.response.activity.QueryAwardReceiveListResponse;
import com.tencent.sr.iris.activity.repository.entity.TIrisUserTaskRecordDO;
import com.tencent.sr.iris.activity.service.activity.ActivityCommonService;
import com.tencent.sr.iris.activity.service.activity.IrisActivityAwardRecordService;
import com.tencent.sr.iris.activity.service.activity.impl.IrisBatchDataServiceImpl;
import com.tencent.sr.iris.activity.service.config.SceneConfig;
import com.tencent.sr.iris.activity.service.constant.ActivityRedisKey;
import com.tencent.sr.iris.activity.service.event.EventStandardService;
import com.tencent.sr.iris.activity.service.event.dto.SyncEventDTO;
import com.tencent.sr.iris.activity.service.event.job.ActivityTaskEventRetryJob;
import com.tencent.sr.iris.activity.service.event.job.MonthGiftPublishEventJob;
import com.tencent.sr.iris.activity.service.event.job.UserActivityTaskBatchDataJobIncrement;
import com.tencent.sr.iris.activity.service.event.job.UserActivityTaskRecordStatusFixJob;
import com.tencent.sr.iris.activity.service.event.job.UserAwardRetryJob;
import com.tencent.sr.iris.activity.service.event.vo.DistributionOrderAggrVO;
import com.tencent.sr.iris.activity.service.kafka.listener.UserEventListener;
import com.tencent.sr.iris.user.core.service.interfaces.request.message.UserActivityLevelUpRequest;
import com.tencent.sr.iris.user.core.service.interfaces.response.user.UserLevelCountResponse;
import com.tencent.sr.rmall.common.exception.retail.TRetailErrorException;
import com.tencent.sr.rmall.common.primitive.HttpResult;
import com.tencent.sr.rmall.springbootstarter.redis.RedisClient;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

import java.time.LocalDate;
import java.util.*;
import javax.annotation.Resource;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.util.Pair;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * 描述用途
 *
 * @author wruiiwang
 * @date 2023/2/19
 */
@Slf4j
@Api(tags = "测试接口", value = "测试接口")
@RestController
@RequestMapping(value = {"/api/v1/iris/iris-activity-core-service/test/"})
public class TestController {

    @Autowired
    private UserCoreDependency userCoreDependency;

    @Autowired
    private SceneConfig sceneConfig;

    @Resource
    private UserAwardRetryJob userAwardRetryJob;

    @Resource
    private ActivityTaskEventRetryJob activityTaskEventRetryJob;

    @Resource
    private UserActivityTaskRecordStatusFixJob userActivityTaskRecordStatusFixJob;
    @Resource
    private ActivityCommonService activityCommonService;

    @Resource
    private UserActivityTaskBatchDataJobIncrement userActivityTaskBatchDataJobIncrement;

    @Resource
    private MonthGiftPublishEventJob monthGiftPublishEventJob;

    @Resource
    private EventStandardService eventStandardService;

    @Resource
    private IrisBatchDataServiceImpl irisBatchDataService;

    @Value("${kafka.topics.activityLevelUpTopic}")
    private String activityLevelUpTopic;

    @PostMapping("traineeTime")
    public HttpResult traineeTime(@RequestBody @Validated UserBaseRequest request) {
        Long traineeTime = activityCommonService.queryTraineeTime(request.getUid());
        return HttpResult.succ(ImmutableMap.of("traineeTime", traineeTime));
    }

    @PostMapping("unionOpenId")
    public HttpResult unionOpenId(@RequestBody @Validated UserBaseRequest request) {
        Pair<String, String> pair = userCoreDependency.queryUnionOpenIdByUid(request.getUid());
        Map<String, String> map = ImmutableMap.of("unionId", pair.getFirst(), "openId", pair.getSecond());
        return HttpResult.succ(map);
    }

    @PostMapping("scene/config")
    public HttpResult sceneConfig() {
        Map<String, SceneInfoMappingDTO> result = new HashMap<>();
        Map<String, SceneInfoMappingDTO> sceneIdMap = sceneConfig.getSceneIdMap();
        for (Map.Entry<String, SceneInfoMappingDTO> entry : sceneIdMap.entrySet()) {
            result.put(entry.getKey(), entry.getValue().clone());
        }
        return HttpResult.succ(result);
    }

    @Resource
    UserEventListener userEventListener;

    @PostMapping("event")
    @ApiOperation(value = "event", httpMethod = "POST")
    public HttpResult<List<UserLevelCountResponse>> event(
            @Validated @RequestBody ActivityEventDTO request) {
        Entry entry = null;
        // 务必保证 finally 会被执行
        try {
            // 资源名可使用任意有业务语义的字符串，注意数目不能太多（超过 1K），超出几千请作为参数传入而不要直接作为资源名
            // EntryType 代表流量类型（inbound/outbound），其中系统规则只对 IN 类型的埋点生效
            entry = SphU.entry("iris_activity_event");
            userEventListener.handleEvent(JSON.toJSONString(request));
            // 被保护的业务逻辑
            // do something...
        } catch (BlockException ex) {
            log.error("营销活动kafka事件接收触发限流");
            throw new TRetailErrorException("被限流");
            // 资源访问阻止，被限流或被降级
            // 进行相应的处理操作
        } catch (Exception ex) {
            // 若需要配置降级规则，需要通过这种方式记录业务异常
            Tracer.traceEntry(ex, entry);
        } finally {
            // 务必保证 exit，务必保证每个 entry 与 exit 配对
            if (entry != null) {
                entry.exit();
            }
        }

        return null;
    }


    @PostMapping("taskBatchDataIncrement")
    @ApiOperation(value = "taskBatchDataIncrement", httpMethod = "POST")
    public HttpResult<Boolean> taskBatchDataIncrement(@RequestBody JSONObject json) {
        String uid = json.getString("uid");
        ShardingContext shardingContext = null;
        if (StrUtil.isNotBlank(uid)) {
            ShardingContexts shardingContexts = new ShardingContexts("mock", "mock", 1, uid, Collections.emptyMap());
            shardingContext = new ShardingContext(shardingContexts, 1);
        }
        userActivityTaskBatchDataJobIncrement.execute(shardingContext);
        return HttpResult.succ(true);
    }

    @PostMapping("monthGiftPublishEventExec")
    @ApiOperation(value = "构建事件去触发月月领定时任务执行", httpMethod = "POST")
    public HttpResult<Boolean> monthGiftPublishEventExec() {
        monthGiftPublishEventJob.execute(null);
        return HttpResult.succ(true);
    }

    @Resource
    private IrisActivityAwardRecordService irisActivityAwardRecordService;
    @Resource
    private RedisClient redisClient;

    /**
     * 清理弹窗标识
     *
     * @param request
     * @return
     */
    @PostMapping("clearPoppedToday")
    @ApiOperation(value = "clearPoppedToday", httpMethod = "POST")
    public HttpResult<Boolean> clearPoppedToday(@RequestBody @Validated ActivityGiftPopupRequest request) {
        String userOpenAppTagKey = ActivityRedisKey.getUserOpenAppTagKey(request.getUid());
        String userAwardPopupTagKey = ActivityRedisKey.getUserAwardPopupTagKey(request.getUid(), request.getTaskId());
        String userAwardTimeKey = ActivityRedisKey.getUserAwardTimeKey(request.getUid(), request.getTaskId(),
                LocalDate.now().toString());
        redisClient.del(userOpenAppTagKey, userAwardPopupTagKey, userAwardTimeKey);
        return HttpResult.succ(true);
    }


    @PostMapping("queryAwardReceiveList")
    @ApiOperation(value = "queryAwardReceiveList", httpMethod = "POST")
    public HttpResult<List<QueryAwardReceiveListResponse>> queryAwardReceiveList(@RequestBody JSONObject param) {
        List<String> outTradeNoList = param.getJSONArray("outTradeNoList").toJavaList(String.class);
        List<QueryAwardReceiveListResponse> receiveList = activityCommonService.queryAwardReceiveList(outTradeNoList);

        return HttpResult.succ(receiveList);
    }

    @PostMapping("querySelfGMVInfo")
    @ApiOperation(value = "querySelfGMVInfo", httpMethod = "POST")
    public HttpResult<Integer> queryAwardReceiveList(@RequestBody QuerySelfBuyGMVReq param) {
        Integer res = activityCommonService
                .querySelfBuyGMVInfo(param.getUids().get(0), param.getSalesDateBegin(), param.getSalesDateEnd());
        return HttpResult.succ(res);
    }

    @PostMapping("orderEventOrgMsgMock")
    @ApiOperation(value = "orderEventOrgMsgMock", httpMethod = "POST")
    public HttpResult<String> orderEventOrgMsgMock(@RequestBody DistributionOrderAggrVO param) {
        eventStandardService.handleDistributionOrderMsg(param);
        return HttpResult.succ("");
    }

    @PostMapping("handleUserActivityLevelUpMsg")
    @ApiOperation(value = "处理用户升级消息", httpMethod = "POST")
    public HttpResult<Boolean> handleUserActivityLevelUpMsg(@RequestBody UserActivityLevelUpRequest userActivityLevelUpRequest) {
        eventStandardService.handleUserActivityLevelUpMsg(userActivityLevelUpRequest);
        return HttpResult.succ(Boolean.TRUE);
    }

    @PostMapping("handleBatchDataSync")
    @ApiOperation(value = "跑批数据同步", httpMethod = "POST")
    public HttpResult<Boolean> handleBatchDataSync(@RequestBody SyncEventDTO<TIrisUserTaskRecordDO> req) {
        irisBatchDataService.handleBatchDataSync(req);
        return HttpResult.succ(Boolean.TRUE);
    }

}
